Simple Game On ZK

From Documentation
Simple Game On ZK

Author
Pashkin Mikhail
Date
July 23, 2012
Version
ZK 6.0.1


Preface

Fifteen puzzle game implementation by Pashkin Mikhail on a single ZUML page.

Parepare game panel

Create necessary visible elements:

        <vlayout sclass="s-container" width="200px" height="200px">

            <hlayout>
                <div id="1" onClick="doClick(self)"/>
                <div id="2" onClick="doClick(self)"/>
                <div id="3" onClick="doClick(self)"/>
                <div id="4" onClick="doClick(self)"/>
            </hlayout>

            <hlayout>
                <div id="5" onClick="doClick(self)"/>
                <div id="6" onClick="doClick(self)"/>
                <div id="7" onClick="doClick(self)"/>
                <div id="8" onClick="doClick(self)"/>
            </hlayout>

            <hlayout>
                <div id="9" onClick="doClick(self)"/>
                <div id="10" onClick="doClick(self)"/>
                <div id="11" onClick="doClick(self)"/>
                <div id="12" onClick="doClick(self)"/>
            </hlayout>

            <hlayout>
                <div id="13" onClick="doClick(self)"/>
                <div id="14" onClick="doClick(self)"/>
                <div id="15" onClick="doClick(self)"/>
                <div id="16" onClick="doClick(self)"/>
            </hlayout>

        </vlayout>

Add styles

We need some style customization to improve UI:

            div.s-container {
                border: 1px black solid;
                padding-top: 2px;
                padding-left: 2px;
            }

            div.s-container div.z-vlayout-inner {
                padding-bottom: 2px !important;
            }

            div.s-container div.z-vlayout-inner  div.z-hlayout div.z-hlayout-inner {
                padding-right: 2px !important;
            }

            div.s-container div.z-vlayout-inner  div.z-hlayout div.z-hlayout-inner div {
                width: 46px;
                height: 46px;
                text-align: center;
                line-height: 50px;
                border: 1px black solid;
            }

            div.s-container div.z-vlayout-inner  div.z-hlayout div.z-hlayout-inner div:hover {
                cursor: pointer;
                background: #8BB0F5;
            }

            div.s-container div.z-vlayout-inner  div.z-hlayout div.z-hlayout-inner div.s-empty {
                border: none;
                padding-right: 2px;
            }

            div.s-container div.z-vlayout-inner  div.z-hlayout div.z-hlayout-inner div:hover.s-empty {
                cursor: default;
                background: none;
            }

Add some scripts

1. Remember our empty element:

                Div emptyDiv;

2. Replace empty cell with the current one:

                void doClick(Div clickedDiv) {
                               if (emptyDiv == clickedDiv) {
                                               return;
                               }

                               if (!isNear(Integer.parseInt(emptyDiv.id), Integer.parseInt(clickedDiv.id))) {
                                               return;
                               }

                               clickedDiv.sclass = "s-empty";
                               emptyDiv.sclass = "";
                               emptyDiv.getChildren().add(clickedDiv.firstChild);
                               emptyDiv = clickedDiv;

                               if (hasWon()) {
                                               alert("You won!");
                                               mix();
                               }
                }

3. Replace only elements which are near each other:

                boolean isNear(int id1, int id2) {
                               return id1 == id2 + 1 || id1 == id2 - 1 || id1 == id2 + 4 || id1 == id2 - 4;
                }

4. Check if the game is over

                boolean hasWon() {
                               for (int i = 1; i <= 16; i++) {
                                               final Label label = self.query("#" + i).firstChild;
                                               if (label == null) {
                                                               if (i != 16) {
                                                                              return false;
                                                              }
                                               } else {
                                                               if (Integer.parseInt(label.value) != i) {
                                                                              return false;
                                                               }
                                               }
                               }

                               return true;
                }

5. And mix all elements:

                void mix() {
                               final Random random = new Random();
                               final List list = new ArrayList(16);
                               for (int i = 1; i <= 16; i++) {
                                               list.add(i);
                               }

                               for (int i = 1; i <= 16; i++) {
                                               final Div currentDiv = self.query("#" + i);
                                               final int currentNumber = list.remove(random.nextInt(list.size()));
                                               if (currentNumber == 16) {
                                                               if (currentDiv.getFirstChild() != null) {
                                                                              currentDiv.getFirstChild().detach();
                                                               }
                                                               currentDiv.sclass="s-empty";
                                                               emptyDiv = currentDiv;
                                               } else {
                                                               if (currentDiv.getFirstChild() == null) {
                                                                              currentDiv.getChildren().add(new Label());
                                                               }
                                                               currentDiv.firstChild.value = String.valueOf(currentNumber);
                                                               currentDiv.sclass="";
                                               }
                               }
                }

Compose all parts together

<?xml version="1.0" encoding="UTF-8"?>

<zk xmlns="http://www.zkoss.org/2005/zul" xmlns:n="native">
    <window title="Fifteen Puzzle Game" border="normal" width="226px" onCreate="mix()">

        <n:style>

            <!-- Styles -->

        </n:style>

        <zscript><![CDATA[

                <!-- Some script -->

        ]]></zscript>

        <!-- Visible elements -->

    </window>
</zk>

Run and enjoy

Fifteen.png

Summary

ZK does simplify web application GUI development.


Comments



Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.